package cc.autoapi.pucong.auto.flow.persistence.repository.log;


import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.node.ExecNode;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.node.ExecParamIn;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.node.ExecParamOut;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.node.TaskNode;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.exception.AutoDesignException;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.exec.DataBus;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.selfenum.RunStatusEnum;
import cc.autoapi.pucong.auto.flow.core.root.utils.UUID;
import cc.autoapi.pucong.auto.flow.persistence.po.log.ApiInstanceNodePo;
import cc.autoapi.pucong.auto.flow.persistence.utils.jdbc.DatabaseUtils;
import com.alibaba.fastjson2.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author pucong
 * @description 项目接口实例节点日志 service 实现类
 * @create 2024-10-07
 */
@Service
public class ApiInstanceNodeServiceImpl implements ApiInstanceNodeService {

    @Override
    public void updateNodeStatus(String apiId, String instanceId, String nodeId, String instanceNodeId, RunStatusEnum runStatus, Date createTime) {
        ApiInstanceNodePo apiInstanceNodePo = null;
        apiInstanceNodePo = getOne(instanceId, nodeId);
        if (apiInstanceNodePo == null) {
            List<TaskNode> taskNodeList = DataBus.getTaskNodeList(apiId);
            TaskNode po = taskNodeList.stream().filter(node -> node.getUuid().equals(nodeId)).findFirst().orElse(null);
            if (po == null) {
                throw new AutoDesignException("未找到该节点信息");
            }
            apiInstanceNodePo = new ApiInstanceNodePo();
            apiInstanceNodePo.setUuid(UUID.uuid());
            apiInstanceNodePo.setApiId(apiId);
            apiInstanceNodePo.setApiNodeId(po.getUuid());
            apiInstanceNodePo.setApiInstanceId(instanceId);
            apiInstanceNodePo.setNodeName(po.getNodeName());
            apiInstanceNodePo.setNodeScript(po.getNodeScript());
            apiInstanceNodePo.setNodeTag(po.getNodeTag());
            apiInstanceNodePo.setProcessInstanceId(po.getProcessId());
            apiInstanceNodePo.setExeStatus(3);
            apiInstanceNodePo.setCreateTime(createTime);
            save(apiInstanceNodePo);
        }
        if (runStatus != null) {
            if (runStatus == RunStatusEnum.执行中) {
                ExecNode execNodeById = getExecNodeById(instanceId, instanceNodeId);
                List<ExecParamIn> paramInList = execNodeById.getParamInList();
                JSONObject jsonObject = new JSONObject();
                for (ExecParamIn execParamIn : paramInList) {
                    jsonObject.put(execParamIn.getParamCode(), execParamIn.getDateValue());
                }
                String result = jsonObject.toJSONString();
                ApiInstanceNodePo update = new ApiInstanceNodePo();
                update.setUuid(apiInstanceNodePo.getUuid());
                update.setParamsIn(result);
                update.setExeStatus(2);
                update.setExeStartTime(createTime);
                updateById(update);
            } else {
                ApiInstanceNodePo update = new ApiInstanceNodePo();
                update.setUuid(apiInstanceNodePo.getUuid());
                if (runStatus == RunStatusEnum.执行成功) {
                    ExecNode execNodeById = getExecNodeById(instanceId, instanceNodeId);
                    List<ExecParamOut> paramOutList = execNodeById.getParamOutList();
                    JSONObject jsonObject = new JSONObject();
                    for (ExecParamOut execParamOut : paramOutList) {
                        Boolean returnValue = execParamOut.getReturnValue();
                        if (returnValue) {
                            jsonObject.put(execParamOut.getParamCode(), execParamOut.getDateValue());
                        }
                    }
                    String result = jsonObject.toJSONString();
                    update.setExeStatus(1);
                    update.setParamsOut(result);
                    update.setExeEndTime(createTime);
                } else if (runStatus == RunStatusEnum.执行失败) {
                    update.setExeStatus(0);
                    update.setExeEndTime(createTime);
                } else if (runStatus == RunStatusEnum.已跳过) {
                    update.setExeStatus(4);
                }
                updateById(update);
            }
        }
    }

    private void updateById(ApiInstanceNodePo update) {
        DatabaseUtils.updateAutoById("auto_flow_api_instance_node", update);

    }

    private void save(ApiInstanceNodePo apiInstanceNodePo) {
        DatabaseUtils.saveAuto("auto_flow_api_instance_node", apiInstanceNodePo);
    }

    @Override
    public void appendApiNodeLog(String apiInstanceId, String apiNodeId, String string) {
        ApiInstanceNodePo apiInstanceNodePo = getOne(apiInstanceId, apiNodeId);
        if (apiInstanceNodePo != null) {
            String logContent = apiInstanceNodePo.getLogContent();
            logContent = logContent + "\n" + string;
            ApiInstanceNodePo update = new ApiInstanceNodePo();
            update.setUuid(apiInstanceNodePo.getUuid());
            update.setLogContent(logContent);
            updateById(update);
        }
    }

    @Override
    public void deleteByApiId(List<String> apiIdS) {
        if (apiIdS.size() == 0) {
            return;
        }
        removeBatchByApiIds(apiIdS);
    }

    private void removeBatchByApiIds(List<String> apiIdS) {
        if (apiIdS == null || apiIdS.size() < 1) {
            return;
        }
        StringBuffer sqlBf = new StringBuffer();
        sqlBf.append("delete from auto_flow_api_instance_node where api_id in (");
        for (int i = 0; i < apiIdS.size(); i++) {
            sqlBf.append("?,");
        }
        sqlBf.deleteCharAt(sqlBf.length() - 1);
        sqlBf.append(")");
        List<Object> params = new ArrayList<>();
        params.addAll(apiIdS);

        DatabaseUtils.execSql(params, sqlBf.toString(), Integer.class);
    }

    @Override
    public List<ApiInstanceNodePo> list(String apiId, String apiNodeId, String apiInstanceId) {
        List<Object> params = new ArrayList<>();
        StringBuffer sqlBf = new StringBuffer();
        sqlBf.append("select * from auto_flow_api_instance_node where 1=1 ");
        if (StringUtils.isNotBlank(apiId)) {
            sqlBf.append(" and api_id = ? ");
            params.add(apiId);
        }
        if (StringUtils.isNotBlank(apiNodeId)) {
            sqlBf.append(" and api_node_id = ? ");
            params.add(apiNodeId);
        }
        if (StringUtils.isNotBlank(apiInstanceId)) {
            sqlBf.append(" and api_instance_id = ? ");
            params.add(apiInstanceId);
        }
        sqlBf.append(" order by create_time desc ");
        List<ApiInstanceNodePo> apiInstanceNodePos = DatabaseUtils.execQueryListSql(params, sqlBf.toString(), ApiInstanceNodePo.class);
        return apiInstanceNodePos;
    }

    @Override
    public ApiInstanceNodePo getOne(String instancesId, String apiNodeId) {
        List<Object> params = new ArrayList<>();
        StringBuffer sqlBf = new StringBuffer();
        sqlBf.append("select * from auto_flow_api_instance_node where 1=1 ");
        if (StringUtils.isNotBlank(apiNodeId)) {
            sqlBf.append(" and api_node_id = ? ");
            params.add(apiNodeId);
        }
        if (StringUtils.isNotBlank(instancesId)) {
            sqlBf.append(" and api_instance_id = ? ");
            params.add(instancesId);
        }
        sqlBf.append(" order by create_time desc ");
        ApiInstanceNodePo apiInstanceNodePo = DatabaseUtils.execQueryOneSql(params, sqlBf.toString(), ApiInstanceNodePo.class);
        return apiInstanceNodePo;
    }

    public ExecNode getExecNodeById(String instanceId, String instanceNodeId) {
        List<ExecNode> execNodeList = DataBus.getExecNodeList(instanceId);
        ExecNode execNode1ById = execNodeList.stream().filter(node -> node.getInstanceNodeId().equals(instanceNodeId)).findFirst().orElse(null);
        return execNode1ById;
    }
}
